package it.infodea.tapestrydea.components.mail;

import it.infodea.tapestrydea.MailObject;
import it.infodea.tapestrydea.services.mail.AttachedFilesManager;
import it.infodea.tapestrydea.services.mail.MailSender;
import it.infodea.tapestrydea.services.mail.impl.AttachedFilesManagerImpl;
import it.infodea.tapestrydea.state.mail.MailState;

import java.io.File;
import java.text.DecimalFormat;
import java.util.List;

import org.apache.tapestry5.Block;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.annotations.ApplicationState;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.IncludeJavaScriptLibrary;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.corelib.components.EventLink;
import org.apache.tapestry5.corelib.components.Form;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.upload.services.UploadedFile;
import org.slf4j.Logger;

@IncludeJavaScriptLibrary("SendMailForm.js")
public class SendMailForm {

	private static final int KILO_BYTE = 1024;

	private static final int MEGA_BYTE = KILO_BYTE * 1024;
	
	private static final String DELETE_ITEM_EVENT_NAME = "delete_item_event";

	private static final String REFRESH_LIST_EVENT_NAME = "refresh_list_event";

	@Parameter
	private AttachedFilesManager attachedManager = new AttachedFilesManagerImpl();
	
	@Parameter
	private Block attachedFilesBlock;
	
	@ApplicationState
	private MailState mailState;
	
	@Inject
	private ComponentResources resources;
	
	@Inject
	private MailSender sender;
	
	@Inject
	private Logger logger;
	
	@Component
	private Form mailForm;
	
	@Component(parameters={"event=" + REFRESH_LIST_EVENT_NAME, "zone=attachedListZone"})
	private EventLink hiddenRefreshLink;

	@Inject
	private Block attachedListBlock;
	
	@Property @Persist
	private MailObject mailObject;
	
	@Property private int index;

	@OnEvent(value=REFRESH_LIST_EVENT_NAME)
	Block onRefresh(){
		return getAttachedFilesBlock();
	}

	@OnEvent(value=AjaxMultipleFileUpload.UPLOAD_EVENT_NAME)
	Block onUpload(UploadedFile uploadedFile){
		
		String fileName = uploadedFile.getFileName();
		String absPath = attachedManager.storeTempAttachedFile(fileName, uploadedFile);
		mailState.add(fileName, absPath, uploadedFile.getSize());
		logger.info("Attachment added " + fileName);
		
		return getAttachedFilesBlock();
	}
	
	@OnEvent(value=DELETE_ITEM_EVENT_NAME)
	Block onDeleteItem(int itemIndex){
			
		String name = mailState.remove(itemIndex);
		logger.info("Attachment removed " + name);
		
		File file = attachedManager.loadTempAttachedFile(name);
		if(file.exists())file.delete();
		return getAttachedFilesBlock();	
	}
	
	public String getDeleteEventName(){
		return DELETE_ITEM_EVENT_NAME;
	}
	
	public Block getAttachedFilesBlock() {
		return resources.isBound("attachedFilesBlock") && attachedFilesBlock != null ?
			attachedFilesBlock : attachedListBlock;
	}
	
	public List<String> getFiles(){
		logger.info("mailState names " + mailState.getNames());
		return mailState.getNames();
	}
	
	public String getFileItem(){
		return mailState.getName(index);
	}
	
	public String getFileSize(){
		return formatSize(mailState.getSize(index), true);
	}
	
	public String getTotal(){
		return formatSize(mailState.getTotal(), false);
	}
	
	public String getCallback(){
		return "function(html){Simulator.simulateClick($('" + hiddenRefreshLink.getClientId() + "'));}";
	}
	
	void onSuccessFromMailForm() {
		mailObject.setAttachments(mailState.getPaths());
		try {
			sender.sendMail(mailObject);
			mailState.clean();
		} catch (Exception e) {
			mailForm.recordError(e.getMessage());
		}
	}
	
	private String formatSize(long bytes, boolean round){
		String format = "%s b";
		String bytesFormat = "0";
		if(bytes > 0){
			double result = bytes;
			if(bytes > MEGA_BYTE){
				result /= MEGA_BYTE;
				if(round){
					result = Math.round(result);
				}
				format = "%s M";
			}else if(bytes > KILO_BYTE){
				result /= KILO_BYTE;
				format = "%s K";
			}
			if(round){
				bytesFormat = String.valueOf(Math.round(result));
			}else{
				bytesFormat = new DecimalFormat("###.##").format(result);
			}
		}
		return String.format(format, bytesFormat);
	}

}
